<template>
  <view class="main">
    <!-- 时间选择器头部标题 -->
    <view class="header">时间：{{ state.selectedTime }}</view>
    <!-- 时间滑块主体 -->
    <view class="time_slider">
      <!-- 时间段容器 -->
      <view class="body" :style="{ height: props.height }">
        <!-- 动态渲染时间块 -->
        <view :class="item.class" v-for="item in state.itemList" :key="item" @touchstart="itemTouchStart(item)"
          @touchmove="itemTouchMove($event, item)" @touchend="itemTouchEnd(item)" :id="'item_' + item.id"
          :time="item.startTime + ' 至' + item.endTime"></view>
      </view>
      <!-- 时间范围标签 -->
      <view class="footer">
        <view>{{ props.startTime }}</view>
        <view>{{ props.endTime }}</view>
      </view>
    </view>
  </view>
</template>

<script lang="ts" setup>
import { reactive, onMounted, getCurrentInstance } from 'vue'

const emit = defineEmits(['change'])
// 获取当前组件实例
const instance = getCurrentInstance();
// 创建选择器查询
const query = uni.createSelectorQuery().in(instance);

// 定义组件props
const props = defineProps({
  /**
   * 高度，带单位
   */
  height: {
    type: String,
    default: '60rpx'
  },
  /**
   * 开始时间
   */
  startTime: {
    type: String,
    default: '08:00'
  },
  /**
   * 结束时间，不支持跨天，结束时间必须大于开始时间
   */
  endTime: {
    type: String,
    default: '18:00'
  },
  //步长，单位为分钟
  step: {
    type: Number,
    default: 10
  },
  /**
   * 默认选中的分钟数
   */
  selectedMinute: {
    type: Number,
    default: 30
  },

  /**
   * 不可用时间段
   */
  inActiveList: {
    type: Array,
    default: () => []
  }
})

// 组件状态管理
const state = reactive({
  itemList: [], // 时间块列表
  inActive: [[12, 20], [55, 60], [80, 87]], // 不可用时间段
  selectLength: 5, // 选择长度
  currentBegin: 0, // 当前可选开始位置
  currentEnd: 99, // 当前可选结束位置
  lock: true, // 选择锁定状态
  selectedTime: "",
})

/**
 * 处理时间块点击事件
 * @param item 点击的时间块对象
 * @param setBeginEnd 是否设置当前开始和结束位置
 */
const itemClick = (item, setBeginEnd = false) => {
  // 检查空白时间段是否足够
  let emptyArray = [];
  for (let i = item.id; i >= 0; i--) {
    if (state.itemList[i].class.includes('item-in-active')) {
      break;
    } else {
      emptyArray.unshift(state.itemList[i])
    }
  }
  for (let i = item.id + 1; i < state.itemList.length; i++) {
    if (state.itemList[i].class.includes('item-in-active')) {
      break;
    } else {
      emptyArray.push(state.itemList[i])
    }
  }

  // 如果空间不够，返回
  if (emptyArray.length < state.selectLength) {
    return
  }

  // 更新当前选择范围
  if (setBeginEnd) {
    state.currentBegin = emptyArray[0].id
    state.currentEnd = emptyArray[emptyArray.length - 1].id
  }

  // 锁定选择在有效范围内
  if (state.lock && (item.id < state.currentBegin || item.id > state.currentEnd)) {
    if (item.id < state.currentBegin) {
      item = state.itemList[state.currentBegin];
    }
    if (item.id > state.currentEnd) {
      item = state.itemList[state.currentEnd - 1];
    }
  }

  // 清除所有已选状态
  state.itemList = state.itemList.map((item) => {
    item.class = item.class.filter((classItem: string) => classItem !== 'item-active')
    return item
  })

  let selectedArray = [];
  // 添加新的选中状态
  if (!item.class.includes('item-in-active')) {
    item.class.push('item-active');
    let startIndex = item.id;
    let lastId = 99;
    for (let i = 0; i < state.selectLength; i++) {
      if (startIndex + i >= state.itemList.length || startIndex + i >= lastId || state.itemList[startIndex + i].class.includes('item-in-active')) {
        if (startIndex + i < lastId) {
          lastId = startIndex + i;
        }
        state.itemList[startIndex + i - state.selectLength].class.push('item-active');
        selectedArray.unshift(state.itemList[startIndex + i - state.selectLength]);
      } else {
        state.itemList[startIndex + i].class.push('item-active');
        selectedArray.push(state.itemList[startIndex + i]);
      }

    }//end for
  }//end if
  //重新按元素的ID正升序排序
  selectedArray.sort((a, b) => a.id - b.id);
  // console.log("🚀====debug==== ~ itemClick ~ selectedArray:", selectedArray)
  state.selectedTime = selectedArray[0].startTime + " - " + selectedArray[selectedArray.length - 1].endTime;
  emit("change", [selectedArray[0].startTime, selectedArray[selectedArray.length - 1].endTime])
}

/**
 * 触摸开始事件处理
 * @param item 被触摸的时间块
 */
const itemTouchStart = (item) => {
  itemClick(item, true)
}

/**
 * 触摸移动事件处理
 * @param event 触摸事件对象
 * @param item 被触摸的时间块
 */
const itemTouchMove = (event, item) => {
  let left = event.changedTouches[0].pageX;
  state.itemList = state.itemList.map((item) => {
    if (item.left <= left && item.right >= left) {
      if (!item.class.includes('item-in-active')) {
        itemClick(item);
      }
    }
    return item
  })
}

/**
 * 触摸结束事件处理
 * @param item 被触摸的时间块
 */
const itemTouchEnd = (item) => {
}

/**
 * 组件挂载后初始化时间块数据
 */
onMounted(() => {
  // 计算时间范围总分钟数
  let minute = calculateMinutes(props.startTime, props.endTime);
  // 根据步长计算时间块数量
  let length = Math.ceil(minute / props.step);
  state.selectLength = Math.ceil(props.selectedMinute / props.step);
  console.log("🚀====debug==== ~ onMounted ~ state.selectLength:", state.selectLength)
  console.log("props.", props.inActiveList);

  state.inActive = [];
  props.inActiveList.forEach((item: Array) => {
    state.inActive.push([getTimePosition(props.startTime, props.step, item[0]), getTimePosition(props.startTime, props.step, item[1]) - 1]);
  });
  console.log("🚀====debug==== ~ props.inActiveList.forEach ~ state.inActive:", state.inActive)
  // 初始化时间块列表
  for (let i = 0; i < length; i++) {
    let itemModel = {
      id: i,
      startTime: calculateEndTime(props.startTime, props.step * i),
      endTime: calculateEndTime(props.startTime, props.step * (i + 1)),
      class: ["item"],
    }
    //如果结束时间大于截止时间，则将结束时间设置为截止时间
    if (itemModel.endTime > props.endTime) {
      itemModel.endTime = props.endTime
    }
    // 判断时间块是否属于不可用时段
    state.inActive.forEach((item) => {
      if (i >= item[0] && i <= item[1]) {
        itemModel.class.push('item-in-active')
      }
    });
    state.itemList.push(itemModel)
  }

  // 设置当前可选范围
  state.currentBegin = 0;
  state.currentEnd = state.itemList.length - 1;
  // console.log("getTimePosition 08:00", getTimePosition("08:00", 10, "08:00"));

  // console.log("getTimePosition 08:20", getTimePosition("08:00", 10, "08:20"));

  // console.log("getTimePosition 09:00", getTimePosition("08:00", 10, "09:00"));

  // console.log("getTimePosition 07:00", getTimePosition("08:00", 10, "07:00"));
  // 延迟执行布局信息获取
  setTimeout(() => {
    setItemList()
  }, 1000);
});

/**
 * 获取时间块布局信息
 */
const setItemList = () => {
  query.selectAll('.item').boundingClientRect().exec((res) => {
    state.itemList = state.itemList.map((item, index) => {
      let resArray = res[0];
      // 存储时间块的位置和尺寸信息
      item.left = resArray[index].left;
      item.top = resArray[index].top;
      item.right = resArray[index].right;
      item.width = resArray[index].width;
      return item;
    })
    // console.log("🚀====debug==== ~ state.itemList=state.itemList.map ~ state.itemList :", state.itemList)
  })
}

//========================公共方法 begin ==================

/**
 * 计算两个时间点之间的分钟数
 * @param startTime 开始时间（格式：HH:mm）
 * @param endTime 结束时间（格式：HH:mm）
 * @returns 返回分钟数差值
 */
const calculateMinutes = (startTime, endTime) => {
  const [startHours, startMinutes] = startTime.split(':').map(Number);
  const [endHours, endMinutes] = endTime.split(':').map(Number);

  const totalStartMinutes = startHours * 60 + startMinutes;
  const totalEndMinutes = endHours * 60 + endMinutes;

  return Math.abs(totalEndMinutes - totalStartMinutes);
}

/**
 * 根据开始时间和分钟数计算结束时间
 * @param startTime 开始时间（格式：HH:mm）
 * @param minutes 要增加的分钟数
 * @returns 返回计算后的结束时间（格式：HH:mm）
 */
const calculateEndTime = (startTime, minutes) => {
  const [hours, mins] = startTime.split(':').map(Number);
  const totalMinutes = hours * 60 + mins + parseInt(minutes);

  const endHours = Math.floor(totalMinutes / 60) % 24;
  const endMinutes = totalMinutes % 60;

  return `${endHours.toString().padStart(2, '0')}:${endMinutes.toString().padStart(2, '0')}`;
}
const getTimePosition = (startTime, stepMinutes, currentTime) => {
  // 解析时间为分钟数
  const parseTime = (timeStr) => {
    const [hours, minutes] = timeStr.split(':').map(Number);
    return hours * 60 + minutes;
  };

  const startMinutes = parseTime(startTime);
  const currentMinutes = parseTime(currentTime);
  const step = parseInt(stepMinutes);

  // 计算差值并确定位置（从1开始计数）
  const position = Math.floor((currentMinutes - startMinutes) / step);
  // 如果当前时间早于开始时间，返回0
  // if (position < 0) return 0;

  // 确保位置不小于1（处理当前时间早于开始时间的情况）
  return position;
}


//========================公共方法 end ==================
</script>

<style lang="scss" scoped>
.main {
  padding: 20rpx;
  font-size: 28rpx;
  box-sizing: border-box;

  .header {
    text-align: center;
  }

  .time_slider {
    padding: 20rpx;
    box-sizing: border-box;

    .body {
      border-radius: 20rpx;
      border: #ccc solid 1rpx;
      height: 60rpx;
      display: flex;
      flex-wrap: nowrap;
      overflow: hidden;

      .item {
        background-color: #fff;
        height: 100%;
        width: 20rpx;
      }

      .item-active {
        background-color: #f00;
      }

      .item-in-active {
        background-color: #ccc;
      }
    }

    .footer {
      display: flex;
      justify-content: space-between;
    }
  }
}
</style>